const fs = require('fs');
const parser = require('@babel/parser');
const traverse = require('@babel/traverse').default;
const path = require('path');
const babel = require('@babel/core');

const getModuleInfo = (file) => {
  const body = fs.readFileSync(file, 'utf-8');  // 转化为字符串
  const ast = parser.parse(body, {
    sourceType: 'module'         // 告诉Babel我们要解析的是ESModule模块
  });  // 转化为ast语法树
  // console.log(ast.program.body);

  const deps = {};  // 依赖收集
  traverse(ast, {
    ImportDeclaration({ node }) {
      const dirname = path.dirname(file);
      const abspath = './' + path.join(dirname, node.source.value);
      deps[node.source.value] = abspath;
    }
  });

  // 代码转换
  const { code } = babel.transformFromAst(ast, null, {
    presets: ["@babel/preset-env"]
  })
  // console.log(code);
  const moduleInfo = { file, deps, code }
  return moduleInfo
}



// 递归获取依赖
const parseModules = (file) => {
  const entry = getModuleInfo(file)
  const temp = [entry]
  for (let i = 0; i < temp.length; i++) {
    const deps = temp[i].deps
    if (deps) {
      for (const key in deps) {    // './add.js'
        if (deps.hasOwnProperty(key)) {
          temp.push(getModuleInfo(deps[key]))
        }
      }
    }
  }
  const depsGraph = {}
  temp.forEach((item) => {
    depsGraph[item.file] = {
      deps: item.deps,
      code: item.code
    }
  })
  console.log(depsGraph);
  return depsGraph
}


// 解析 require 与 exports 关键字
const bundle = (file) => {
  const depsGraph = JSON.stringify(parseModules(file))

  return `(function (graph) {
    function require(file) {
      function absRequire(relPath) {
        return require(graph[file].deps[relPath])
      }
      var exports = {};

      (function (require, exports, code) {
        eval(code)
      })(absRequire, exports, graph[file].code)

      return exports
    }
    require('${file}')
  })(${depsGraph})`
}

const content = bundle('./src/index.js')
// console.log(content);

fs.mkdirSync('./dist')
fs.writeFileSync('./dist/main.js', content)

// parseModules('./src/index.js')

